using System;
using System.Net;
using System.Net.Sockets;
using System.Collections.Generic;
using UnityEngine;

/*
 * SocketManagerBase - 网络通信管理器基类
 * 
 * 功能：
 * 1. 处理TCP网络连接、断开、重连
 * 2. 实现消息队列管理和异步发送
 * 3. 提供消息确认机制和超时重试
 * 4. 实现心跳机制保持连接活跃
 * 5. 抽象化消息格式处理，支持不同消息分割方式
 * 
 * 版本：1.0
 * 作者：yixiang.hui
 * 创建时间：2025.9.4
 * 最后修改：2025.9.4
 */

namespace HyxFrame.Core
{
    /// <summary>
    /// Socket管理器基类，提供网络通信的基础功能
    /// </summary>
    public abstract class SocketManagerBase : MonoSingleton<SocketManagerBase>
    {
        #region 常量定义
        
        /// <summary>
        /// 消息超时时间（秒）
        /// </summary>
        protected const float MESSAGE_TIMEOUT = 5f;
        
        /// <summary>
        /// 心跳间隔时间（秒）
        /// </summary>
        protected const float HEARTBEAT_INTERVAL = 2f;
        
        /// <summary>
        /// 重连间隔时间（秒）
        /// </summary>
        protected const float RECONNECT_INTERVAL = 3f;
        
        #endregion
        
        #region 受保护字段
        
        /// <summary>
        /// 服务器网络端点
        /// </summary>
        protected IPEndPoint serverEndPoint;
        
        /// <summary>
        /// TCP套接字对象
        /// </summary>
        protected Socket socket;
        
        /// <summary>
        /// 接收数据缓冲区（4096字节）
        /// </summary>
        protected byte[] receiveBuffer = new byte[4096];
        
        /// <summary>
        /// 消息队列
        /// </summary>
        protected Queue<string> messageQueue = new Queue<string>();
        
        /// <summary>
        /// 发送状态标志
        /// </summary>
        protected bool isSending = false;
        
        /// <summary>
        /// 队列操作锁对象
        /// </summary>
        protected object queueLock = new object();
        
        /// <summary>
        /// 待确认消息字典
        /// </summary>
        protected Dictionary<int, PendingMessage> pendingMessages = new Dictionary<int, PendingMessage>();
        
        /// <summary>
        /// 消息ID计数器
        /// </summary>
        protected int messageIdCounter = 0;
        
        /// <summary>
        /// 最后心跳时间
        /// </summary>
        protected float lastHeartbeatTime = 0f;
        
        /// <summary>
        /// 连接状态标志
        /// </summary>
        protected bool isConnected = false;
        
        /// <summary>
        /// 最后连接尝试时间
        /// </summary>
        protected float lastConnectAttemptTime = 0f;
        
        #endregion
        
        #region 内部类
        
        /// <summary>
        /// 待处理消息类
        /// </summary>
        protected class PendingMessage
        {
            public int MessageId { get; set; }
            public string Message { get; set; }
            public float SendTime { get; set; }
            public int RetryCount { get; set; }
        }
        
        #endregion
        
        #region Unity生命周期方法
        
        /// <summary>
        /// 初始化管理器
        /// </summary>
        protected override void InitManager() { }
        
        /// <summary>
        /// 每帧更新，处理超时、心跳和重连
        /// </summary>
        private void Update()
        {
            CheckTimeouts();
            CheckHeartbeat();
            CheckReconnection();
        }
        
        #endregion
        
        #region 公共方法
        
        /// <summary>
        /// 初始化网络连接
        /// </summary>
        /// <param name="address">服务器地址</param>
        /// <param name="port">服务器端口</param>
        public void InitNetwork(string address, int port)
        {
            try
            {
                IPAddress ipAddress = IPAddress.Parse(address);
                serverEndPoint = new IPEndPoint(ipAddress, port);
                
                // 创建TCP套接字
                socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                socket.NoDelay = true; // 禁用Nagle算法，降低延迟
                socket.ReceiveBufferSize = 8192;
                socket.SendBufferSize = 8192;
                
                ConnectToServer();
            }
            catch (Exception ex)
            {
                Debug.LogError($"网络初始化失败: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 发送消息到服务器
        /// </summary>
        /// <param name="message">要发送的消息</param>
        public void Send(string message)
        {
            lock (queueLock)
            {
                messageQueue.Enqueue(message);
                
                // 如果当前没有发送操作且已连接，立即处理消息队列
                if (!isSending && IsConnected())
                {
                    ProcessMessageQueue();
                }
            }
        }
        
        /// <summary>
        /// 断开与服务器的连接
        /// </summary>
        public virtual void Disconnect()
        {
            try
            {
                if (IsConnected())
                {
                    socket.Shutdown(SocketShutdown.Both);
                    socket.Close();
                }
                
                socket = null;
                isConnected = false;
                
                // 清空消息队列和状态
                lock (queueLock)
                {
                    messageQueue.Clear();
                    isSending = false;
                }
                
                pendingMessages.Clear();
                
                Debug.Log("成功断开与服务器的连接。");
            }
            catch (Exception ex)
            {
                Debug.LogError($"断开连接失败: {ex.Message}");
            }
        }
        
        #endregion
        
        #region 受保护的连接管理方法
        
        /// <summary>
        /// 连接到服务器
        /// </summary>
        protected virtual void ConnectToServer()
        {
            if (IsConnected())
            {
                Debug.Log("已经连接到服务器。");
                return;
            }
            
            try
            {
                // 开始异步连接
                socket.BeginConnect(serverEndPoint, ConnectCallback, socket);
                lastConnectAttemptTime = Time.time;
            }
            catch (Exception ex)
            {
                Debug.LogError($"尝试连接服务器失败: {ex.Message}");
                ScheduleReconnect();
            }
        }
        
        /// <summary>
        /// 连接回调函数
        /// </summary>
        /// <param name="ar">异步操作结果</param>
        protected virtual void ConnectCallback(IAsyncResult ar)
        {
            try
            {
                socket.EndConnect(ar);
                isConnected = true;
                Debug.Log("成功连接到服务器！");
                
                // 开始异步接收数据
                socket.BeginReceive(receiveBuffer, 0, receiveBuffer.Length, SocketFlags.None, ReceiveCallback, socket);
                
                // 处理可能积压的消息队列
                ProcessMessageQueue();
            }
            catch (Exception ex)
            {
                Debug.LogError($"连接服务器失败: {ex.Message}");
                isConnected = false;
                ScheduleReconnect();
            }
        }
        
        /// <summary>
        /// 安排重连（由子类实现具体逻辑）
        /// </summary>
        protected virtual void ScheduleReconnect() { }
        
        /// <summary>
        /// 检查是否需要重新连接
        /// </summary>
        protected virtual void CheckReconnection()
        {
            if (!IsConnected() && Time.time - lastConnectAttemptTime > RECONNECT_INTERVAL)
            {
                Debug.Log("尝试重新连接服务器...");
                ConnectToServer();
            }
        }
        
        /// <summary>
        /// 检查连接状态
        /// </summary>
        /// <returns>是否已连接</returns>
        protected virtual bool IsConnected()
        {
            return socket != null && socket.Connected && isConnected;
        }
        
        /// <summary>
        /// 处理连接断开
        /// </summary>
        protected virtual void HandleDisconnection()
        {
            isConnected = false;
            Debug.Log("连接已断开");
            ScheduleReconnect();
        }
        
        #endregion
        
        #region 受保护的消息处理方怯
        
        /// <summary>
        /// 处理消息队列
        /// </summary>
        protected virtual void ProcessMessageQueue()
        {
            if (!IsConnected() || isSending) return;
            
            lock (queueLock)
            {
                if (messageQueue.Count == 0)
                {
                    isSending = false;
                    return;
                }
                
                isSending = true;
                string message = messageQueue.Dequeue();
                SendInternal(message);
            }
        }
        
        /// <summary>
        /// 内部发送消息实现
        /// </summary>
        /// <param name="message">要发送的消息</param>
        protected virtual void SendInternal(string message)
        {
            try
            {
                // 生成消息ID并创建待处理消息
                int messageId = ++messageIdCounter;
                var pendingMessage = new PendingMessage
                {
                    MessageId = messageId,
                    Message = message,
                    SendTime = Time.time,
                    RetryCount = 0
                };
                
                pendingMessages[messageId] = pendingMessage;
                
                // 格式化消息并开始异步发送
                byte[] messageBytes = FormatSendMessage(message, messageId);
                socket.BeginSend(messageBytes, 0, messageBytes.Length, SocketFlags.None, SendCallback, socket);
            }
            catch (Exception ex)
            {
                Debug.LogError($"发送消息失败: {ex.Message}");
                isSending = false;
                HandleDisconnection();
            }
        }
        
        /// <summary>
        /// 发送回调函数
        /// </summary>
        /// <param name="ar">异步操作结果</param>
        protected virtual void SendCallback(IAsyncResult ar)
        {
            try
            {
                int bytesSent = socket.EndSend(ar);
                Debug.Log($"成功发送 {bytesSent} 字节到服务器。");
                
                lock (queueLock)
                {
                    isSending = false;
                    ProcessMessageQueue(); // 继续处理队列中的下一条消息
                }
            }
            catch (Exception ex)
            {
                Debug.LogError($"发送消息回调失败: {ex.Message}");
                isSending = false;
                HandleDisconnection();
            }
        }
        
        /// <summary>
        /// 接收回调函数
        /// </summary>
        /// <param name="ar">异步操作结果</param>
        protected virtual void ReceiveCallback(IAsyncResult ar)
        {
            try
            {
                int bytesRead = socket.EndReceive(ar);
                if (bytesRead > 0)
                {
                    // 处理接收到的数据
                    ProcessReceivedData(receiveBuffer, bytesRead);
                    
                    // 继续异步接收
                    socket.BeginReceive(receiveBuffer, 0, receiveBuffer.Length, SocketFlags.None, ReceiveCallback, socket);
                }
                else
                {
                    Debug.Log("服务器关闭了连接。");
                    HandleDisconnection();
                }
            }
            catch (Exception ex)
            {
                Debug.LogError($"接收消息回调失败: {ex.Message}");
                HandleDisconnection();
            }
        }
        
        /// <summary>
        /// 处理确认消息
        /// </summary>
        /// <param name="ackMessage">确认消息内容</param>
        protected virtual void HandleAcknowledgment(string ackMessage)
        {
            try
            {
                string[] parts = ackMessage.Split(':');
                if (parts.Length >= 2 && int.TryParse(parts[1], out int messageId))
                {
                    if (pendingMessages.ContainsKey(messageId))
                    {
                        pendingMessages.Remove(messageId);
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.LogError($"处理确认消息失败: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 处理普通消息
        /// </summary>
        /// <param name="message">消息内容</param>
        protected virtual void HandleMessage(string message)
        {
            Debug.Log($"接收到完整消息: {message}");
        }
        
        /// <summary>
        /// 检查消息超时
        /// </summary>
        protected virtual void CheckTimeouts()
        {
            List<int> timeoutMessages = new List<int>();
            float currentTime = Time.time;
            
            foreach (var kvp in pendingMessages)
            {
                if (currentTime - kvp.Value.SendTime > MESSAGE_TIMEOUT)
                {
                    if (kvp.Value.RetryCount < 3)
                    {
                        // 重试发送
                        kvp.Value.RetryCount++;
                        kvp.Value.SendTime = currentTime;
                        SendInternal(kvp.Value.Message);
                    }
                    else
                    {
                        // 添加到超时列表
                        timeoutMessages.Add(kvp.Key);
                    }
                }
            }
            
            // 移除超时消息
            foreach (int messageId in timeoutMessages)
            {
                pendingMessages.Remove(messageId);
                Debug.LogWarning($"消息 {messageId} 超时，已放弃");
            }
        }
        
        /// <summary>
        /// 检查并发送心跳
        /// </summary>
        protected virtual void CheckHeartbeat()
        {
            if (!IsConnected()) return;
            
            if (Time.time - lastHeartbeatTime > HEARTBEAT_INTERVAL)
            {
                SendInternal("HEARTBEAT");
                lastHeartbeatTime = Time.time;
            }
        }
        
        #endregion
        
        #region 抽象方法（由子类实现）
        
        /// <summary>
        /// 处理接收到的数据
        /// </summary>
        /// <param name="data">接收到的字节数组</param>
        /// <param name="bytesRead">实际读取的字节数</param>
        protected abstract void ProcessReceivedData(byte[] data, int bytesRead);
        
        /// <summary>
        /// 格式化发送消息
        /// </summary>
        /// <param name="message">原始消息</param>
        /// <param name="messageId">消息ID</param>
        /// <returns>格式化后的字节数组</returns>
        protected abstract byte[] FormatSendMessage(string message, int messageId);
        
        /// <summary>
        /// 发送确认消息
        /// </summary>
        /// <param name="message">需要确认的原始消息</param>
        protected abstract void SendAcknowledgment(string message);
        
        #endregion
    }
}